home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / ImageFile.py < prev    next >
Text File  |  2006-12-03  |  15KB  |  521 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: ImageFile.py 2930 2006-12-02 13:50:40Z fredrik $
  4. #
  5. # base class for image file handlers
  6. #
  7. # history:
  8. # 1995-09-09 fl   Created
  9. # 1996-03-11 fl   Fixed load mechanism.
  10. # 1996-04-15 fl   Added pcx/xbm decoders.
  11. # 1996-04-30 fl   Added encoders.
  12. # 1996-12-14 fl   Added load helpers
  13. # 1997-01-11 fl   Use encode_to_file where possible
  14. # 1997-08-27 fl   Flush output in _save
  15. # 1998-03-05 fl   Use memory mapping for some modes
  16. # 1999-02-04 fl   Use memory mapping also for "I;16" and "I;16B"
  17. # 1999-05-31 fl   Added image parser
  18. # 2000-10-12 fl   Set readonly flag on memory-mapped images
  19. # 2002-03-20 fl   Use better messages for common decoder errors
  20. # 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available
  21. # 2003-10-30 fl   Added StubImageFile class
  22. # 2004-02-25 fl   Made incremental parser more robust
  23. #
  24. # Copyright (c) 1997-2004 by Secret Labs AB
  25. # Copyright (c) 1995-2004 by Fredrik Lundh
  26. #
  27. # See the README file for information on usage and redistribution.
  28. #
  29.  
  30. import Image
  31. import traceback, sys, string, os
  32.  
  33. MAXBLOCK = 65536
  34.  
  35. SAFEBLOCK = 1024*1024
  36.  
  37. ERRORS = {
  38.     -1: "image buffer overrun error",
  39.     -2: "decoding error",
  40.     -3: "unknown error",
  41.     -8: "bad configuration",
  42.     -9: "out of memory error"
  43. }
  44.  
  45. #
  46. # --------------------------------------------------------------------
  47. # Helpers
  48.  
  49. def _tilesort(t1, t2):
  50.     # sort on offset
  51.     return cmp(t1[2], t2[2])
  52.  
  53. #
  54. # --------------------------------------------------------------------
  55. # ImageFile base class
  56.  
  57. ##
  58. # Base class for image file handlers.
  59.  
  60. class ImageFile(Image.Image):
  61.     "Base class for image file format handlers."
  62.  
  63.     def __init__(self, fp=None, filename=None):
  64.         Image.Image.__init__(self)
  65.  
  66.         self.tile = None
  67.         self.readonly = 1 # until we know better
  68.  
  69.         self.decoderconfig = ()
  70.         self.decodermaxblock = MAXBLOCK
  71.  
  72.         if Image.isStringType(fp):
  73.             # filename
  74.             self.fp = open(fp, "rb")
  75.             self.filename = fp
  76.         else:
  77.             # stream
  78.             self.fp = fp
  79.             self.filename = filename
  80.  
  81.         try:
  82.             self._open()
  83.         except IndexError, v: # end of data
  84.             if Image.DEBUG > 1:
  85.                 traceback.print_exc()
  86.             raise SyntaxError, v
  87.         except TypeError, v: # end of data (ord)
  88.             if Image.DEBUG > 1:
  89.                 traceback.print_exc()
  90.             raise SyntaxError, v
  91.         except KeyError, v: # unsupported mode
  92.             if Image.DEBUG > 1:
  93.                 traceback.print_exc()
  94.             raise SyntaxError, v
  95.         except EOFError, v: # got header but not the first frame
  96.             if Image.DEBUG > 1:
  97.                 traceback.print_exc()
  98.             raise SyntaxError, v
  99.  
  100.         if not self.mode or self.size[0] <= 0:
  101.             raise SyntaxError, "not identified by this driver"
  102.  
  103.     def draft(self, mode, size):
  104.         "Set draft mode"
  105.  
  106.         pass
  107.  
  108.     def verify(self):
  109.         "Check file integrity"
  110.  
  111.         # raise exception if something's wrong.  must be called
  112.         # directly after open, and closes file when finished.
  113.         self.fp = None
  114.  
  115.     def load(self):
  116.         "Load image data based on tile list"
  117.  
  118.         pixel = Image.Image.load(self)
  119.  
  120.         if self.tile is None:
  121.             raise IOError("cannot load this image")
  122.         if not self.tile:
  123.             return pixel
  124.  
  125.         self.map = None
  126.  
  127.         readonly = 0
  128.  
  129.         if self.filename and len(self.tile) == 1:
  130.             # try memory mapping
  131.             d, e, o, a = self.tile[0]
  132.             if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
  133.                 try:
  134.                     if hasattr(Image.core, "map"):
  135.                         # use built-in mapper
  136.                         self.map = Image.core.map(self.filename)
  137.                         self.map.seek(o)
  138.                         self.im = self.map.readimage(
  139.                             self.mode, self.size, a[1], a[2]
  140.                             )
  141.                     else:
  142.                         # use mmap, if possible
  143.                         import mmap
  144.                         file = open(self.filename, "r+")
  145.                         size = os.path.getsize(self.filename)
  146.                         # FIXME: on Unix, use PROT_READ etc
  147.                         self.map = mmap.mmap(file.fileno(), size)
  148.                         self.im = Image.core.map_buffer(
  149.                             self.map, self.size, d, e, o, a
  150.                             )
  151.                     readonly = 1
  152.                 except (AttributeError, EnvironmentError, ImportError):
  153.                     self.map = None
  154.  
  155.         self.load_prepare()
  156.  
  157.         # look for read/seek overrides
  158.         try:
  159.             read = self.load_read
  160.         except AttributeError:
  161.             read = self.fp.read
  162.  
  163.         try:
  164.             seek = self.load_seek
  165.         except AttributeError:
  166.             seek = self.fp.seek
  167.  
  168.         if not self.map:
  169.  
  170.             # sort tiles in file order
  171.             self.tile.sort(_tilesort)
  172.  
  173.             try:
  174.                 # FIXME: This is a hack to handle TIFF's JpegTables tag.
  175.                 prefix = self.tile_prefix
  176.             except AttributeError:
  177.                 prefix = ""
  178.  
  179.             for d, e, o, a in self.tile:
  180.                 d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
  181.                 seek(o)
  182.                 try:
  183.                     d.setimage(self.im, e)
  184.                 except ValueError:
  185.                     continue
  186.                 b = prefix
  187.                 t = len(b)
  188.                 while 1:
  189.                     s = read(self.decodermaxblock)
  190.                     if not s:
  191.                         self.tile = []
  192.                         raise IOError("image file is truncated (%d bytes not processed)" % len(b))
  193.                     b = b + s
  194.                     n, e = d.decode(b)
  195.                     if n < 0:
  196.                         break
  197.                     b = b[n:]
  198.                     t = t + n
  199.  
  200.         self.tile = []
  201.         self.readonly = readonly
  202.  
  203.         self.fp = None # might be shared
  204.  
  205.         if not self.map and e < 0:
  206.             error = ERRORS.get(e, "decoder error %d" % e)
  207.             raise IOError(error + " when reading image file")
  208.  
  209.         # post processing
  210.         if hasattr(self, "tile_post_rotate"):
  211.             # FIXME: This is a hack to handle rotated PCD's
  212.             self.im = self.im.rotate(self.tile_post_rotate)
  213.             self.size = self.im.size
  214.  
  215.         self.load_end()
  216.  
  217.         return Image.Image.load(self)
  218.  
  219.     def load_prepare(self):
  220.         # create image memory if necessary
  221.         if not self.im or\
  222.            self.im.mode != self.mode or self.im.size != self.size:
  223.             self.im = Image.core.new(self.mode, self.size)
  224.         # create palette (optional)
  225.         if self.mode == "P":
  226.             Image.Image.load(self)
  227.  
  228.     def load_end(self):
  229.         # may be overridden
  230.         pass
  231.  
  232.     # may be defined for contained formats
  233.     # def load_seek(self, pos):
  234.     #     pass
  235.  
  236.     # may be defined for blocked formats (e.g. PNG)
  237.     # def load_read(self, bytes):
  238.     #     pass
  239.  
  240. ##
  241. # Base class for stub image loaders.
  242. # <p>
  243. # A stub loader is an image loader that can identify files of a
  244. # certain format, but relies on external code to load the file.
  245.  
  246. class StubImageFile(ImageFile):
  247.     "Base class for stub image loaders."
  248.  
  249.     def _open(self):
  250.         raise NotImplementedError(
  251.             "StubImageFile subclass must implement _open"
  252.             )
  253.  
  254.     def load(self):
  255.         loader = self._load()
  256.         if loader is None:
  257.             raise IOError("cannot find loader for this %s file" % self.format)
  258.         image = loader.load(self)
  259.         assert image is not None
  260.         # become the other object (!)
  261.         self.__class__ = image.__class__
  262.         self.__dict__ = image.__dict__
  263.  
  264.     ##
  265.     # (Hook) Find actual image loader.
  266.  
  267.     def _load(self):
  268.         raise NotImplementedError(
  269.             "StubImageFile subclass must implement _load"
  270.             )
  271.  
  272. ##
  273. # (Internal) Support class for the <b>Parser</b> file.
  274.  
  275. class _ParserFile:
  276.     # parser support class.
  277.  
  278.     def __init__(self, data):
  279.         self.data = data
  280.         self.offset = 0
  281.  
  282.     def close(self):
  283.         self.data = self.offset = None
  284.  
  285.     def tell(self):
  286.         return self.offset
  287.  
  288.     def seek(self, offset, whence=0):
  289.         if whence == 0:
  290.             self.offset = offset
  291.         elif whence == 1:
  292.             self.offset = self.offset + offset
  293.         else:
  294.             # force error in Image.open
  295.             raise IOError("illegal argument to seek")
  296.  
  297.     def read(self, bytes=0):
  298.         pos = self.offset
  299.         if bytes:
  300.             data = self.data[pos:pos+bytes]
  301.         else:
  302.             data = self.data[pos:]
  303.         self.offset = pos + len(data)
  304.         return data
  305.  
  306.     def readline(self):
  307.         # FIXME: this is slow!
  308.         s = ""
  309.         while 1:
  310.             c = self.read(1)
  311.             if not c:
  312.                 break
  313.             s = s + c
  314.             if c == "\n":
  315.                 break
  316.         return s
  317.  
  318. ##
  319. # Incremental image parser.  This class implements the standard
  320. # feed/close consumer interface.
  321.  
  322. class Parser:
  323.  
  324.     incremental = None
  325.     image = None
  326.     data = None
  327.     decoder = None
  328.     finished = 0
  329.  
  330.     ##
  331.     # (Consumer) Reset the parser.  Note that you can only call this
  332.     # method immediately after you've created a parser; parser
  333.     # instances cannot be reused.
  334.  
  335.     def reset(self):
  336.         assert self.data is None, "cannot reuse parsers"
  337.  
  338.     ##
  339.     # (Consumer) Feed data to the parser.
  340.     #
  341.     # @param data A string buffer.
  342.     # @exception IOError If the parser failed to parse the image file.
  343.  
  344.     def feed(self, data):
  345.         # collect data
  346.  
  347.         if self.finished:
  348.             return
  349.  
  350.         if self.data is None:
  351.             self.data = data
  352.         else:
  353.             self.data = self.data + data
  354.  
  355.         # parse what we have
  356.         if self.decoder:
  357.  
  358.             if self.offset > 0:
  359.                 # skip header
  360.                 skip = min(len(self.data), self.offset)
  361.                 self.data = self.data[skip:]
  362.                 self.offset = self.offset - skip
  363.                 if self.offset > 0 or not self.data:
  364.                     return
  365.  
  366.             n, e = self.decoder.decode(self.data)
  367.  
  368.             if n < 0:
  369.                 # end of stream
  370.                 self.data = None
  371.                 self.finished = 1
  372.                 if e < 0:
  373.                     # decoding error
  374.                     self.image = None
  375.                     error = ERRORS.get(e, "decoder error %d" % e)
  376.                     raise IOError(error + " when reading image file")
  377.                 else:
  378.                     # end of image
  379.                     return
  380.             self.data = self.data[n:]
  381.  
  382.         elif self.image:
  383.  
  384.             # if we end up here with no decoder, this file cannot
  385.             # be incrementally parsed.  wait until we've gotten all
  386.             # available data
  387.             pass
  388.  
  389.         else:
  390.  
  391.             # attempt to open this file
  392.             try:
  393.                 try:
  394.                     fp = _ParserFile(self.data)
  395.                     im = Image.open(fp)
  396.                 finally:
  397.                     fp.close() # explicitly close the virtual file
  398.             except IOError:
  399.                 pass # not enough data
  400.             else:
  401.                 flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
  402.                 if flag or len(im.tile) != 1:
  403.                     # custom load code, or multiple tiles
  404.                     self.decode = None
  405.                 else:
  406.                     # initialize decoder
  407.                     im.load_prepare()
  408.                     d, e, o, a = im.tile[0]
  409.                     im.tile = []
  410.                     self.decoder = Image._getdecoder(
  411.                         im.mode, d, a, im.decoderconfig
  412.                         )
  413.                     self.decoder.setimage(im.im, e)
  414.  
  415.                     # calculate decoder offset
  416.                     self.offset = o
  417.                     if self.offset <= len(self.data):
  418.                         self.data = self.data[self.offset:]
  419.                         self.offset = 0
  420.  
  421.                 self.image = im
  422.  
  423.     ##
  424.     # (Consumer) Close the stream.
  425.     #
  426.     # @return An image object.
  427.     # @exception IOError If the parser failed to parse the image file.
  428.  
  429.     def close(self):
  430.         # finish decoding
  431.         if self.decoder:
  432.             # get rid of what's left in the buffers
  433.             self.feed("")
  434.             self.data = self.decoder = None
  435.             if not self.finished:
  436.                 raise IOError("image was incomplete")
  437.         if not self.image:
  438.             raise IOError("cannot parse this image")
  439.         if self.data:
  440.             # incremental parsing not possible; reopen the file
  441.             # not that we have all data
  442.             try:
  443.                 fp = _ParserFile(self.data)
  444.                 self.image = Image.open(fp)
  445.             finally:
  446.                 fp.close() # explicitly close the virtual file
  447.         return self.image
  448.  
  449. # --------------------------------------------------------------------
  450.  
  451. ##
  452. # (Helper) Save image body to file.
  453. #
  454. # @param im Image object.
  455. # @param fp File object.
  456. # @param tile Tile list.
  457.  
  458. def _save(im, fp, tile):
  459.     "Helper to save image based on tile list"
  460.  
  461.     im.load()
  462.     if not hasattr(im, "encoderconfig"):
  463.         im.encoderconfig = ()
  464.     tile.sort(_tilesort)
  465.     # FIXME: make MAXBLOCK a configuration parameter
  466.     bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c
  467.     try:
  468.         fh = fp.fileno()
  469.         fp.flush()
  470.     except AttributeError:
  471.         # compress to Python file-compatible object
  472.         for e, b, o, a in tile:
  473.             e = Image._getencoder(im.mode, e, a, im.encoderconfig)
  474.             if o > 0:
  475.                 fp.seek(o, 0)
  476.             e.setimage(im.im, b)
  477.             while 1:
  478.                 l, s, d = e.encode(bufsize)
  479.                 fp.write(d)
  480.                 if s:
  481.                     break
  482.             if s < 0:
  483.                 raise IOError("encoder error %d when writing image file" % s)
  484.     else:
  485.         # slight speedup: compress to real file object
  486.         for e, b, o, a in tile:
  487.             e = Image._getencoder(im.mode, e, a, im.encoderconfig)
  488.             if o > 0:
  489.                 fp.seek(o, 0)
  490.             e.setimage(im.im, b)
  491.             s = e.encode_to_file(fh, bufsize)
  492.             if s < 0:
  493.                 raise IOError("encoder error %d when writing image file" % s)
  494.     try:
  495.         fp.flush()
  496.     except: pass
  497.  
  498.  
  499. ##
  500. # Reads large blocks in a safe way.  Unlike fp.read(n), this function
  501. # doesn't trust the user.  If the requested size is larger than
  502. # SAFEBLOCK, the file is read block by block.
  503. #
  504. # @param fp File handle.  Must implement a <b>read</b> method.
  505. # @param size Number of bytes to read.
  506. # @return A string containing up to <i>size</i> bytes of data.
  507.  
  508. def _safe_read(fp, size):
  509.     if size <= 0:
  510.         return ""
  511.     if size <= SAFEBLOCK:
  512.         return fp.read(size)
  513.     data = []
  514.     while size > 0:
  515.         block = fp.read(min(size, SAFEBLOCK))
  516.         if not block:
  517.             break
  518.         data.append(block)
  519.         size = size - len(block)
  520.     return string.join(data, "")
  521.